{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd8e6326",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.llms import OpenAI\n",
    "from langchain.agents import AgentExecutor, create_react_agent\n",
    "\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "template = '''Answer the following questions as best you can. You have access to the following tools:\n",
    "\n",
    "{tools}\n",
    "\n",
    "Use the following format:\n",
    "\n",
    "Question: the input question you must answer\n",
    "Thought: you should always think about what to do\n",
    "Action: the action to take, should be one of [{tool_names}]\n",
    "Action Input: the input to the action\n",
    "Observation: the result of the action\n",
    "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "Thought: I now know the final answer\n",
    "Final Answer: the final answer to the original input question\n",
    "\n",
    "Begin!\n",
    "\n",
    "Question: {input}\n",
    "Thought:{agent_scratchpad}'''\n",
    "\n",
    "prompt = PromptTemplate.from_template(template)\n",
    "\n",
    "model = OpenAI()\n",
    "tools = ...\n",
    "\n",
    "agent = create_react_agent(model, tools, prompt)\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools)\n",
    "\n",
    "agent_executor.invoke({\"input\": \"hi\"})\n",
    "\n",
    "# Use with chat history\n",
    "from langchain_core.messages import AIMessage, HumanMessage\n",
    "agent_executor.invoke(\n",
    "    {\n",
    "        \"input\": \"what's my name?\",\n",
    "        # Notice that chat_history is a string\n",
    "        # since this prompt is aimed at LLMs, not chat models\n",
    "        \"chat_history\": \"Human: My name is Bob\\nAI: Hello Bob!\",\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b50cb7dc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 物流 ReACT Agent===\n",
      "\n",
      "--- 测试案例 1 ---\n",
      "问题: 查询快递单号 SF123456\n",
      "--------------------------------------------------\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m需要使用TrackPackage工具查询快递单号状态\n",
      "Action: TrackPackage\n",
      "Action Input: SF123456\u001b[0m\u001b[36;1m\u001b[1;3m快递单号: SF123456, 状态: 运输中, 位置: 北京分拣中心, 预计送达: 2024-01-15\u001b[0m\u001b[32;1m\u001b[1;3mFinal Answer: 快递单号 SF123456 的状态为运输中，当前位置在北京分拣中心，预计送达时间为 2024-01-15。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\n",
      "最终答案: 快递单号 SF123456 的状态为运输中，当前位置在北京分拣中心，预计送达时间为 2024-01-15。\n",
      "执行步骤数: 1\n",
      "\n",
      "============================================================\n",
      "\n",
      "--- 测试案例 2 ---\n",
      "问题: 从北京到上海寄2公斤包裹多少钱\n",
      "--------------------------------------------------\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m需要计算运费\n",
      "Action: CalculateShipping\n",
      "Action Input: 北京,上海,2\u001b[0m\u001b[33;1m\u001b[1;3m运费计算结果: 从北京到上海，重量2.0kg，运费: 12.0元\u001b[0m\u001b[32;1m\u001b[1;3mFinal Answer: 从北京到上海寄2公斤包裹的运费是12元。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\n",
      "最终答案: 从北京到上海寄2公斤包裹的运费是12元。\n",
      "执行步骤数: 1\n",
      "\n",
      "============================================================\n",
      "\n",
      "--- 测试案例 3 ---\n",
      "问题: 查询商品A001的库存\n",
      "--------------------------------------------------\n",
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m需要查询商品A001的库存，应该使用CheckInventory工具。\n",
      "Action: CheckInventory\n",
      "Action Input: A001\u001b[0m\u001b[38;5;200m\u001b[1;3m商品代码: A001, 名称: iPhone 15, 库存: 150件, 仓库: 上海仓, 状态: 有货\u001b[0m\u001b[32;1m\u001b[1;3mFinal Answer: 商品代码为A001的iPhone 15在上海仓有150件库存，状态为有货。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\n",
      "最终答案: 商品代码为A001的iPhone 15在上海仓有150件库存，状态为有货。\n",
      "执行步骤数: 1\n",
      "\n",
      "============================================================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.llms import Tongyi\n",
    "from langchain.agents import AgentExecutor, create_react_agent\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.tools import Tool\n",
    "\n",
    "# 物流场景的 Mock 工具\n",
    "\n",
    "def track_package(tracking_number):\n",
    "    \"\"\"包裹追踪工具\"\"\"\n",
    "    tracking_number = str(tracking_number).strip()\n",
    "    \n",
    "    package_status = {\n",
    "        \"SF123456\": {\n",
    "            \"status\": \"运输中\",\n",
    "            \"location\": \"北京分拣中心\",\n",
    "            \"estimated_delivery\": \"2024-01-15\"\n",
    "        },\n",
    "        \"YT789012\": {\n",
    "            \"status\": \"已签收\",\n",
    "            \"location\": \"上海浦东\",\n",
    "            \"delivery_date\": \"2024-01-10\"\n",
    "        }\n",
    "    }\n",
    "    \n",
    "    if tracking_number in package_status:\n",
    "        info = package_status[tracking_number]\n",
    "        if 'estimated_delivery' in info:\n",
    "            return f\"快递单号: {tracking_number}, 状态: {info['status']}, 位置: {info['location']}, 预计送达: {info['estimated_delivery']}\"\n",
    "        else:\n",
    "            return f\"快递单号: {tracking_number}, 状态: {info['status']}, 位置: {info['location']}, 送达日期: {info['delivery_date']}\"\n",
    "    else:\n",
    "        return f\"未找到快递单号 {tracking_number} 的信息\"\n",
    "\n",
    "def calculate_shipping_cost(params):\n",
    "    \"\"\"运费计算工具\"\"\"\n",
    "    try:\n",
    "        if ',' in params:\n",
    "            parts = params.split(',')\n",
    "            origin = parts[0].strip()\n",
    "            destination = parts[1].strip()\n",
    "            weight = float(parts[2].strip())\n",
    "        else:\n",
    "            return \"请输入正确格式: 起始城市,目的城市,重量\"\n",
    "        \n",
    "        base_cost = 10\n",
    "        weight_cost = max(0, (weight - 1)) * 2\n",
    "        total_cost = base_cost + weight_cost\n",
    "        \n",
    "        return f\"运费计算结果: 从{origin}到{destination}，重量{weight}kg，运费: {total_cost}元\"\n",
    "    except Exception as e:\n",
    "        return f\"计算错误，请输入正确格式: 起始城市,目的城市,重量。错误: {str(e)}\"\n",
    "\n",
    "def check_inventory(product_code):\n",
    "    \"\"\"库存查询工具\"\"\"\n",
    "    product_code = str(product_code).strip()\n",
    "    \n",
    "    inventory = {\n",
    "        \"A001\": {\"name\": \"iPhone 15\", \"stock\": 150, \"warehouse\": \"上海仓\"},\n",
    "        \"B002\": {\"name\": \"MacBook Pro\", \"stock\": 45, \"warehouse\": \"深圳仓\"},\n",
    "        \"C003\": {\"name\": \"iPad Air\", \"stock\": 0, \"warehouse\": \"北京仓\"}\n",
    "    }\n",
    "    \n",
    "    if product_code in inventory:\n",
    "        item = inventory[product_code]\n",
    "        status = \"有货\" if item['stock'] > 0 else \"缺货\"\n",
    "        return f\"商品代码: {product_code}, 名称: {item['name']}, 库存: {item['stock']}件, 仓库: {item['warehouse']}, 状态: {status}\"\n",
    "    else:\n",
    "        return f\"未找到商品代码 {product_code} 的信息\"\n",
    "\n",
    "# 创建工具\n",
    "tools = [\n",
    "    Tool(\n",
    "        name=\"TrackPackage\",\n",
    "        description=\"追踪包裹状态，输入快递单号\",\n",
    "        func=track_package\n",
    "    ),\n",
    "    Tool(\n",
    "        name=\"CalculateShipping\",\n",
    "        description=\"计算运费，输入格式：起始城市,目的城市,重量(如：北京,上海,2)\",\n",
    "        func=calculate_shipping_cost\n",
    "    ),\n",
    "    Tool(\n",
    "        name=\"CheckInventory\", \n",
    "        description=\"查询库存，输入商品代码\",\n",
    "        func=check_inventory\n",
    "    )\n",
    "]\n",
    "\n",
    "# 简化的 ReACT 提示模板\n",
    "template = '''Answer the following questions as best you can. You have access to the following tools:\n",
    "\n",
    "{tools}\n",
    "\n",
    "Use the following format:\n",
    "\n",
    "Question: the input question you must answer\n",
    "Thought: you should always think about what to do\n",
    "Action: the action to take, should be one of [{tool_names}]\n",
    "Action Input: the input to the action\n",
    "Observation: the result of the action\n",
    "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "Thought: I now know the final answer\n",
    "Final Answer: the final answer to the original input question\n",
    "\n",
    "Begin!\n",
    "\n",
    "Question: {input}\n",
    "Thought:{agent_scratchpad}'''\n",
    "\n",
    "prompt = PromptTemplate.from_template(template)\n",
    "\n",
    "# 初始化通义千问模型\n",
    "try:\n",
    "    model = Tongyi(temperature=0)\n",
    "    agent = create_react_agent(model, tools, prompt)\n",
    "    agent_executor = AgentExecutor(\n",
    "        agent=agent, \n",
    "        tools=tools, \n",
    "        verbose=True,\n",
    "        handle_parsing_errors=True,\n",
    "        max_iterations=3,\n",
    "        return_intermediate_steps=True\n",
    "    )\n",
    "    \n",
    "    # 测试案例\n",
    "    if __name__ == \"__main__\":\n",
    "        print(\"=== 物流 ReACT Agent===\\n\")\n",
    "        \n",
    "        test_cases = [\n",
    "            \"查询快递单号 SF123456\",\n",
    "            \"从北京到上海寄2公斤包裹多少钱\", \n",
    "            \"查询商品A001的库存\"\n",
    "        ]\n",
    "        \n",
    "        for i, question in enumerate(test_cases, 1):\n",
    "            print(f\"--- 测试案例 {i} ---\")\n",
    "            print(f\"问题: {question}\")\n",
    "            print(\"-\" * 50)\n",
    "            \n",
    "            try:\n",
    "                result = agent_executor.invoke({\"input\": question})\n",
    "                print(f\"\\n最终答案: {result.get('output', '无结果')}\")\n",
    "                \n",
    "                # 显示中间步骤\n",
    "                if 'intermediate_steps' in result:\n",
    "                    print(f\"执行步骤数: {len(result['intermediate_steps'])}\")\n",
    "                    \n",
    "            except Exception as e:\n",
    "                print(f\"Agent执行错误: {e}\")\n",
    "                \n",
    "                # 提供备选答案，确保用户能看到正确结果\n",
    "                print(\"\\n使用直接工具调用作为备选:\")\n",
    "                if i == 1:  # 查询快递单号\n",
    "                    backup_result = track_package(\"SF123456\")\n",
    "                    print(f\"备选答案: {backup_result}\")\n",
    "                elif i == 2:  # 计算运费\n",
    "                    backup_result = calculate_shipping_cost(\"北京,上海,2\")\n",
    "                    print(f\"备选答案: {backup_result}\")\n",
    "                elif i == 3:  # 查询库存\n",
    "                    backup_result = check_inventory(\"A001\")\n",
    "                    print(f\"备选答案: {backup_result}\")\n",
    "            \n",
    "            print(\"\\n\" + \"=\"*60 + \"\\n\")\n",
    "        \n",
    "\n",
    "except Exception as e:\n",
    "    print(f\"初始化错误: {e}\")\n",
    "    print(\"请确保已设置 DASHSCOPE_API_KEY 环境变量\")\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3283819",
   "metadata": {},
   "source": [
    "## FSM 状态机"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cd119bd9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 基于状态机的订单处理系统（LangChain完整版） ===\n",
      "\n",
      "LangChain LLM 初始化成功\n",
      "--- 演示1: 未付款订单的完整流程 ---\n",
      "=== 开始处理订单 ORD001 ===\n",
      "\n",
      "步骤1: 验证订单\n",
      "  执行节点: validate_order_node\n",
      "  当前状态: 开始\n",
      "结果: 订单验证成功！  \n",
      "**订单号：** ORD001  \n",
      "**客户：** 张三  \n",
      "**商品：** iPhone 15  \n",
      "**金额：** 7999元  \n",
      "\n",
      "感谢您的确认，我们将尽快为您安排发货。如有任何疑问，请随时联系客服。\n",
      "状态转换: 订单已验证\n",
      "\n",
      "步骤2: 检查付款状态\n",
      "  执行节点: check_payment_node\n",
      "  当前状态: 订单已验证\n",
      "结果: 订单尚未完成付款，请先完成支付以继续后续处理。感谢您的配合！\n",
      "状态转换: 付款状态已检查\n",
      "\n",
      "步骤3: 处理付款\n",
      "  执行节点: process_payment_node\n",
      "  当前状态: 付款状态已检查\n",
      "结果: 付款处理完成。金额：7999元，方式：微信支付，交易号：TXNORD001-2024。感谢您的支付！\n",
      "状态转换: 付款已处理\n",
      "\n",
      "步骤4: 开具发票\n",
      "  执行节点: generate_invoice_node\n",
      "  当前状态: 付款已处理\n",
      "结果: 发票开具完成确认：\n",
      "\n",
      "发票号：INVORD001-2024  \n",
      "金额：7999元  \n",
      "类型：增值税专用发票  \n",
      "\n",
      "感谢您的确认！如有任何问题，请随时联系。\n",
      "状态转换: 发票已开具\n",
      "\n",
      "步骤5: 结束流程\n",
      "  执行节点: end_node\n",
      "  当前状态: 发票已开具\n",
      "结果: 订单处理流程已顺利完成，所有步骤均成功执行。感谢您的配合！\n",
      "状态转换: 结束\n",
      "\n",
      "--- 最终状态 ---\n",
      "\n",
      "当前状态: 结束\n",
      "流程上下文: {\n",
      "  \"order_number\": \"ORD001\",\n",
      "  \"order_info\": {\n",
      "    \"customer\": \"张三\",\n",
      "    \"product\": \"iPhone 15\",\n",
      "    \"amount\": 7999,\n",
      "    \"date\": \"2024-01-10\",\n",
      "    \"payment_status\": \"未付款\"\n",
      "  },\n",
      "  \"payment_confirmed\": true,\n",
      "  \"payment_amount\": 7999,\n",
      "  \"payment_method\": \"微信支付\",\n",
      "  \"transaction_id\": \"TXNORD001-2024\",\n",
      "  \"invoice_number\": \"INVORD001-2024\",\n",
      "  \"invoice_amount\": 7999,\n",
      "  \"invoice_type\": \"增值税专用发票\",\n",
      "  \"invoice_status\": \"已开具\"\n",
      "}\n",
      "\n",
      "状态转换历史:\n",
      "  1. 开始 → 订单已验证 (验证订单)\n",
      "  2. 订单已验证 → 付款状态已检查 (检查付款状态)\n",
      "  3. 付款状态已检查 → 付款已处理 (处理付款)\n",
      "  4. 付款已处理 → 发票已开具 (开具发票)\n",
      "  5. 发票已开具 → 结束 (结束流程)\n",
      "\n",
      "================================================================================\n",
      "\n",
      "--- 演示2: 已付款订单的流程 ---\n",
      "=== 开始处理订单 ORD003 ===\n",
      "\n",
      "步骤1: 验证订单\n",
      "  执行节点: validate_order_node\n",
      "  当前状态: 开始\n",
      "结果: 订单验证成功！  \n",
      "**订单号：** ORD003  \n",
      "**客户：** 王五  \n",
      "**商品：** iPad Air  \n",
      "**金额：** 4999元  \n",
      "\n",
      "感谢您的确认！如有任何问题，请随时联系我们。\n",
      "状态转换: 订单已验证\n",
      "\n",
      "步骤2: 检查付款状态\n",
      "  执行节点: check_payment_node\n",
      "  当前状态: 订单已验证\n",
      "结果: 确认消息如下：\n",
      "\n",
      "**订单付款已确认，可直接开具发票。**\n",
      "\n",
      "如需进一步操作或提供发票信息，请随时告知。\n",
      "状态转换: 付款已处理\n",
      "\n",
      "步骤3: 跳过付款处理（订单已付款）\n",
      "当前状态保持: 付款已处理\n",
      "\n",
      "步骤4: 开具发票\n",
      "  执行节点: generate_invoice_node\n",
      "  当前状态: 付款已处理\n",
      "结果: 发票开具完成确认：\n",
      "\n",
      "发票号：INVORD003-2024  \n",
      "金 额：4999元  \n",
      "类 型：电子普通发票\n",
      "\n",
      "感谢您的确认！如需进一步协助，请随时联系。\n",
      "状态转换: 发票已开具\n",
      "\n",
      "步骤5: 结束流程\n",
      "  执行节点: end_node\n",
      "  当前状态: 发票已开具\n",
      "结果: 订单处理流程已顺利完成，所有步骤已成功执行。感谢您的配合！\n",
      "状态转换: 结束\n",
      "\n",
      "--- 最终状态 ---\n",
      "\n",
      "当前状态: 结束\n",
      "流程上下文: {\n",
      "  \"order_number\": \"ORD003\",\n",
      "  \"order_info\": {\n",
      "    \"customer\": \"王五\",\n",
      "    \"product\": \"iPad Air\",\n",
      "    \"amount\": 4999,\n",
      "    \"date\": \"2024-01-12\",\n",
      "    \"payment_status\": \"已付款\"\n",
      "  },\n",
      "  \"payment_confirmed\": true,\n",
      "  \"invoice_number\": \"INVORD003-2024\",\n",
      "  \"invoice_amount\": 4999,\n",
      "  \"invoice_type\": \"电子普通发票\",\n",
      "  \"invoice_status\": \"已开具\"\n",
      "}\n",
      "\n",
      "状态转换历史:\n",
      "  1. 开始 → 订单已验证 (验证订单)\n",
      "  2. 订单已验证 → 付款已处理 (检查付款状态)\n",
      "  3. 付款已处理 → 发票已开具 (开具发票)\n",
      "  4. 发票已开具 → 结束 (结束流程)\n",
      "\n",
      "================================================================================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.llms import Tongyi\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from enum import Enum\n",
    "from typing import Dict, Any, Optional\n",
    "import json\n",
    "\n",
    "# 定义订单处理状态\n",
    "class OrderState(Enum):\n",
    "    START = \"开始\"\n",
    "    ORDER_VALIDATED = \"订单已验证\"\n",
    "    PAYMENT_CHECKED = \"付款状态已检查\"\n",
    "    PAYMENT_PROCESSED = \"付款已处理\"\n",
    "    INVOICE_GENERATED = \"发票已开具\"\n",
    "    END = \"结束\"\n",
    "    ERROR = \"错误\"\n",
    "\n",
    "# 状态机图定义（类似LangGraph的节点和边）\n",
    "class OrderProcessGraph:\n",
    "    def __init__(self):\n",
    "        self.current_state = OrderState.START\n",
    "        self.context = {}\n",
    "        self.history = []\n",
    "        \n",
    "        # Mock数据\n",
    "        self.orders = {\n",
    "            \"ORD001\": {\n",
    "                \"customer\": \"张三\",\n",
    "                \"product\": \"iPhone 15\", \n",
    "                \"amount\": 7999,\n",
    "                \"date\": \"2024-01-10\",\n",
    "                \"payment_status\": \"未付款\"\n",
    "            },\n",
    "            \"ORD002\": {\n",
    "                \"customer\": \"李四\",\n",
    "                \"product\": \"MacBook Pro\",\n",
    "                \"amount\": 15999, \n",
    "                \"date\": \"2024-01-08\",\n",
    "                \"payment_status\": \"未付款\"\n",
    "            },\n",
    "            \"ORD003\": {\n",
    "                \"customer\": \"王五\",\n",
    "                \"product\": \"iPad Air\",\n",
    "                \"amount\": 4999,\n",
    "                \"date\": \"2024-01-12\", \n",
    "                \"payment_status\": \"已付款\"\n",
    "            }\n",
    "        }\n",
    "        \n",
    "        # 初始化LLM\n",
    "        self.llm = None\n",
    "        try:\n",
    "            self.llm = Tongyi(temperature=0)\n",
    "            print(\"LangChain LLM 初始化成功\")\n",
    "        except Exception as e:\n",
    "            print(f\"LLM初始化失败，使用默认消息: {e}\")\n",
    "    \n",
    "    def add_to_history(self, from_state: OrderState, to_state: OrderState, action: str, result: str):\n",
    "        \"\"\"添加历史记录\"\"\"\n",
    "        self.history.append({\n",
    "            'from': from_state.value,\n",
    "            'to': to_state.value,\n",
    "            'action': action,\n",
    "            'result': result\n",
    "        })\n",
    "    \n",
    "    def generate_message_with_llm(self, template_str: str, variables: Dict) -> str:\n",
    "        \"\"\"使用LangChain LLM生成消息\"\"\"\n",
    "        if not self.llm:\n",
    "            # 回退到默认消息\n",
    "            return template_str.format(**variables)\n",
    "        \n",
    "        try:\n",
    "            prompt = PromptTemplate.from_template(template_str + \" 请生成一个专业简洁的确认消息。\")\n",
    "            chain = prompt | self.llm | StrOutputParser()\n",
    "            return chain.invoke(variables)\n",
    "        except Exception as e:\n",
    "            print(f\"LLM调用失败，使用默认消息: {e}\")\n",
    "            return template_str.format(**variables)\n",
    "    \n",
    "    # 节点函数（类似LangGraph的节点）\n",
    "    def validate_order_node(self, order_number: str) -> Dict[str, Any]:\n",
    "        \"\"\"验证订单节点\"\"\"\n",
    "        print(f\"  执行节点: validate_order_node\")\n",
    "        print(f\"  当前状态: {self.current_state.value}\")\n",
    "        \n",
    "        if self.current_state != OrderState.START:\n",
    "            message = f\"错误：当前状态为 {self.current_state.value}，无法验证订单\"\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "        \n",
    "        if order_number in self.orders:\n",
    "            order_info = self.orders[order_number]\n",
    "            self.context.update({\n",
    "                'order_number': order_number,\n",
    "                'order_info': order_info\n",
    "            })\n",
    "            \n",
    "            # 使用LangChain生成消息\n",
    "            template = \"订单验证成功！订单号: {order_number}, 客户: {customer}, 商品: {product}, 金额: {amount}元\"\n",
    "            message = self.generate_message_with_llm(template, {\n",
    "                'order_number': order_number,\n",
    "                'customer': order_info['customer'],\n",
    "                'product': order_info['product'],\n",
    "                'amount': order_info['amount']\n",
    "            })\n",
    "            \n",
    "            self.add_to_history(self.current_state, OrderState.ORDER_VALIDATED, \"验证订单\", message)\n",
    "            self.current_state = OrderState.ORDER_VALIDATED\n",
    "            \n",
    "            return {\n",
    "                'success': True,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ORDER_VALIDATED\n",
    "            }\n",
    "        else:\n",
    "            message = f\"订单号 {order_number} 不存在\"\n",
    "            self.add_to_history(self.current_state, OrderState.ERROR, \"验证订单\", message)\n",
    "            self.current_state = OrderState.ERROR\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "    \n",
    "    def check_payment_node(self) -> Dict[str, Any]:\n",
    "        \"\"\"检查付款状态节点\"\"\"\n",
    "        print(f\"  执行节点: check_payment_node\")\n",
    "        print(f\"  当前状态: {self.current_state.value}\")\n",
    "        \n",
    "        if self.current_state != OrderState.ORDER_VALIDATED:\n",
    "            message = f\"错误：当前状态为 {self.current_state.value}，无法检查付款状态\"\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "        \n",
    "        order_info = self.context.get('order_info', {})\n",
    "        payment_status = order_info.get('payment_status', '未付款')\n",
    "        \n",
    "        if payment_status == '已付款':\n",
    "            template = \"付款状态检查完成：订单已付款，可以直接开具发票\"\n",
    "            message = self.generate_message_with_llm(template, {})\n",
    "            self.context['payment_confirmed'] = True\n",
    "            next_state = OrderState.PAYMENT_PROCESSED\n",
    "        else:\n",
    "            template = \"付款状态检查完成：订单未付款，需要先处理付款\"\n",
    "            message = self.generate_message_with_llm(template, {})\n",
    "            self.context['payment_confirmed'] = False\n",
    "            next_state = OrderState.PAYMENT_CHECKED\n",
    "        \n",
    "        self.add_to_history(self.current_state, next_state, \"检查付款状态\", message)\n",
    "        self.current_state = next_state\n",
    "        \n",
    "        return {\n",
    "            'success': True,\n",
    "            'message': message,\n",
    "            'next_state': next_state,\n",
    "            'payment_status': payment_status\n",
    "        }\n",
    "    \n",
    "    def process_payment_node(self, payment_method: str = \"支付宝\") -> Dict[str, Any]:\n",
    "        \"\"\"处理付款节点\"\"\"\n",
    "        print(f\"  执行节点: process_payment_node\")\n",
    "        print(f\"  当前状态: {self.current_state.value}\")\n",
    "        \n",
    "        if self.current_state != OrderState.PAYMENT_CHECKED:\n",
    "            message = f\"错误：当前状态为 {self.current_state.value}，无法处理付款\"\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "        \n",
    "        order_info = self.context.get('order_info', {})\n",
    "        amount = order_info.get('amount', 0)\n",
    "        order_number = self.context.get('order_number', '000')\n",
    "        \n",
    "        # 使用LangChain生成付款确认消息\n",
    "        template = \"付款处理完成！付款金额: {amount}元，付款方式: {payment_method}，交易号: TXN{order_number}-2024\"\n",
    "        message = self.generate_message_with_llm(template, {\n",
    "            'amount': amount,\n",
    "            'payment_method': payment_method,\n",
    "            'order_number': order_number\n",
    "        })\n",
    "        \n",
    "        self.context.update({\n",
    "            'payment_amount': amount,\n",
    "            'payment_method': payment_method,\n",
    "            'transaction_id': f\"TXN{order_number}-2024\",\n",
    "            'payment_confirmed': True\n",
    "        })\n",
    "        \n",
    "        self.add_to_history(self.current_state, OrderState.PAYMENT_PROCESSED, \"处理付款\", message)\n",
    "        self.current_state = OrderState.PAYMENT_PROCESSED\n",
    "        \n",
    "        return {\n",
    "            'success': True,\n",
    "            'message': message,\n",
    "            'next_state': OrderState.PAYMENT_PROCESSED\n",
    "        }\n",
    "    \n",
    "    def generate_invoice_node(self, invoice_type: str = \"电子发票\") -> Dict[str, Any]:\n",
    "        \"\"\"开具发票节点\"\"\"\n",
    "        print(f\"  执行节点: generate_invoice_node\")\n",
    "        print(f\"  当前状态: {self.current_state.value}\")\n",
    "        \n",
    "        if self.current_state != OrderState.PAYMENT_PROCESSED:\n",
    "            message = f\"错误：当前状态为 {self.current_state.value}，无法开具发票。必须先完成付款处理\"\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "        \n",
    "        order_info = self.context.get('order_info', {})\n",
    "        amount = order_info.get('amount', 0)\n",
    "        order_number = self.context.get('order_number', '000')\n",
    "        invoice_number = f\"INV{order_number}-2024\"\n",
    "        \n",
    "        # 使用LangChain生成发票确认消息\n",
    "        template = \"发票开具完成！发票号: {invoice_number}，金额: {amount}元，类型: {invoice_type}\"\n",
    "        message = self.generate_message_with_llm(template, {\n",
    "            'invoice_number': invoice_number,\n",
    "            'amount': amount,\n",
    "            'invoice_type': invoice_type\n",
    "        })\n",
    "        \n",
    "        self.context.update({\n",
    "            'invoice_number': invoice_number,\n",
    "            'invoice_amount': amount,\n",
    "            'invoice_type': invoice_type,\n",
    "            'invoice_status': '已开具'\n",
    "        })\n",
    "        \n",
    "        self.add_to_history(self.current_state, OrderState.INVOICE_GENERATED, \"开具发票\", message)\n",
    "        self.current_state = OrderState.INVOICE_GENERATED\n",
    "        \n",
    "        return {\n",
    "            'success': True,\n",
    "            'message': message,\n",
    "            'next_state': OrderState.INVOICE_GENERATED\n",
    "        }\n",
    "    \n",
    "    def end_node(self) -> Dict[str, Any]:\n",
    "        \"\"\"结束节点\"\"\"\n",
    "        print(f\"  执行节点: end_node\")\n",
    "        print(f\"  当前状态: {self.current_state.value}\")\n",
    "        \n",
    "        if self.current_state != OrderState.INVOICE_GENERATED:\n",
    "            message = f\"错误：当前状态为 {self.current_state.value}，流程未完成\"\n",
    "            return {\n",
    "                'success': False,\n",
    "                'message': message,\n",
    "                'next_state': OrderState.ERROR\n",
    "            }\n",
    "        \n",
    "        # 使用LangChain生成结束消息\n",
    "        template = \"订单处理流程已完成，所有步骤执行成功\"\n",
    "        message = self.generate_message_with_llm(template, {})\n",
    "        \n",
    "        self.add_to_history(self.current_state, OrderState.END, \"结束流程\", message)\n",
    "        self.current_state = OrderState.END\n",
    "        \n",
    "        return {\n",
    "            'success': True,\n",
    "            'message': message,\n",
    "            'next_state': OrderState.END\n",
    "        }\n",
    "    \n",
    "    # 边函数（类似LangGraph的条件边）\n",
    "    def should_process_payment(self) -> bool:\n",
    "        \"\"\"判断是否需要处理付款\"\"\"\n",
    "        return not self.context.get('payment_confirmed', False)\n",
    "    \n",
    "    def get_status(self) -> str:\n",
    "        \"\"\"获取当前状态\"\"\"\n",
    "        result = f\"\"\"\n",
    "当前状态: {self.current_state.value}\n",
    "流程上下文: {json.dumps(self.context, ensure_ascii=False, indent=2)}\n",
    "\"\"\"\n",
    "        \n",
    "        if self.history:\n",
    "            result += f\"\\n状态转换历史:\\n\"\n",
    "            for i, step in enumerate(self.history, 1):\n",
    "                result += f\"  {i}. {step['from']} → {step['to']} ({step['action']})\\n\"\n",
    "        \n",
    "        return result\n",
    "    \n",
    "    def reset(self):\n",
    "        \"\"\"重置状态机\"\"\"\n",
    "        self.current_state = OrderState.START\n",
    "        self.context = {}\n",
    "        self.history = []\n",
    "\n",
    "# 订单处理执行器（类似LangGraph的执行器）\n",
    "class OrderProcessExecutor:\n",
    "    def __init__(self):\n",
    "        self.graph = OrderProcessGraph()\n",
    "    \n",
    "    def execute_workflow(self, order_number: str, payment_method: str = \"支付宝\", invoice_type: str = \"电子发票\"):\n",
    "        \"\"\"执行完整的工作流程\"\"\"\n",
    "        print(f\"=== 开始处理订单 {order_number} ===\\n\")\n",
    "        \n",
    "        # 步骤1: 验证订单\n",
    "        print(\"步骤1: 验证订单\")\n",
    "        result1 = self.graph.validate_order_node(order_number)\n",
    "        print(f\"结果: {result1['message']}\")\n",
    "        print(f\"状态转换: {self.graph.current_state.value}\\n\")\n",
    "        \n",
    "        if not result1['success']:\n",
    "            return result1\n",
    "        \n",
    "        # 步骤2: 检查付款状态\n",
    "        print(\"步骤2: 检查付款状态\")\n",
    "        result2 = self.graph.check_payment_node()\n",
    "        print(f\"结果: {result2['message']}\")\n",
    "        print(f\"状态转换: {self.graph.current_state.value}\\n\")\n",
    "        \n",
    "        if not result2['success']:\n",
    "            return result2\n",
    "        \n",
    "        # 条件分支：如果未付款，则处理付款\n",
    "        if self.graph.should_process_payment():\n",
    "            print(\"步骤3: 处理付款\")\n",
    "            result3 = self.graph.process_payment_node(payment_method)\n",
    "            print(f\"结果: {result3['message']}\")\n",
    "            print(f\"状态转换: {self.graph.current_state.value}\\n\")\n",
    "            \n",
    "            if not result3['success']:\n",
    "                return result3\n",
    "        else:\n",
    "            print(\"步骤3: 跳过付款处理（订单已付款）\")\n",
    "            print(f\"当前状态保持: {self.graph.current_state.value}\\n\")\n",
    "        \n",
    "        # 步骤4: 开具发票\n",
    "        print(\"步骤4: 开具发票\")\n",
    "        result4 = self.graph.generate_invoice_node(invoice_type)\n",
    "        print(f\"结果: {result4['message']}\")\n",
    "        print(f\"状态转换: {self.graph.current_state.value}\\n\")\n",
    "        \n",
    "        if not result4['success']:\n",
    "            return result4\n",
    "        \n",
    "        # 步骤5: 结束流程\n",
    "        print(\"步骤5: 结束流程\")\n",
    "        result5 = self.graph.end_node()\n",
    "        print(f\"结果: {result5['message']}\")\n",
    "        print(f\"状态转换: {self.graph.current_state.value}\\n\")\n",
    "        \n",
    "        return result5\n",
    "    \n",
    "    def get_status(self):\n",
    "        \"\"\"获取状态\"\"\"\n",
    "        return self.graph.get_status()\n",
    "    \n",
    "    def reset(self):\n",
    "        \"\"\"重置\"\"\"\n",
    "        self.graph.reset()\n",
    "\n",
    "def demo_fsm_langchain_complete():\n",
    "    \"\"\"演示完整的LangChain集成FSM实现\"\"\"\n",
    "    print(\"=== 基于状态机的订单处理系统（LangChain完整版） ===\\n\")\n",
    "    \n",
    "    executor = OrderProcessExecutor()\n",
    "    \n",
    "    # 演示1: 未付款订单的完整流程\n",
    "    print(\"--- 演示1: 未付款订单的完整流程 ---\")\n",
    "    result1 = executor.execute_workflow(\"ORD001\", \"微信支付\", \"增值税专用发票\")\n",
    "    \n",
    "    print(\"--- 最终状态 ---\")\n",
    "    print(executor.get_status())\n",
    "    print(\"=\"*80 + \"\\n\")\n",
    "    \n",
    "    # 演示2: 已付款订单的流程\n",
    "    print(\"--- 演示2: 已付款订单的流程 ---\")\n",
    "    executor.reset()\n",
    "    result2 = executor.execute_workflow(\"ORD003\", \"支付宝\", \"电子普通发票\")\n",
    "    \n",
    "    print(\"--- 最终状态 ---\")\n",
    "    print(executor.get_status())\n",
    "    print(\"=\"*80 + \"\\n\")\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    demo_fsm_langchain_complete()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MLOps",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
